# -*- coding: utf-8 -*-
import logging
import httplib, urllib, json
import operator, hashlib
import redis, urllib2
from ftplib import FTP
from StringIO import StringIO
from django.conf import settings
from news.models import NewsCategory

logger = logging.getLogger(__name__)

class DBUtils:
    @staticmethod
    def __db_select_multi(cursor, sql_select_str):
        try:
            cursor.execute(sql_select_str)
            rows = cursor.fetchall()
            return rows
        except Exception as e:
            logger.exception(sql_select_str)
            raise e
    
    @staticmethod
    def get_data_by_batch(cursor, sql_str, args, start_offset, batch_count):
        result_list = []
        offset = start_offset
        while True:
            sql_select_str = sql_str % (args + (offset, batch_count))
            rows = DBUtils.__db_select_multi(cursor, sql_select_str)
            if rows != None:
                result_list += [tuple(row) for row in rows]
            else:
                break

            if len(rows) < batch_count:
                break
            offset += batch_count

        return result_list
    
class StringUtils:

    @staticmethod
    def strQ2B(ustring):
        """把字符串全角转半角"""
        rstring = ""
        for uchar in ustring:
            inside_code = ord(uchar)
            if inside_code == 0x3000:
                inside_code = 0x0020
            else:
                inside_code -= 0xfee0
            if not inside_code in range(32, 127): #转完之后不是半角字符返回原来的字符
                rstring += uchar
            else:
                rstring += unichr(inside_code)
        return rstring
    
    @staticmethod
    def escape_stock_name_string(orig_str):
        # 去空格，转义单引号，全角转半角
        tmp_str = orig_str.replace(" ", "").replace('\'', '\'\'')
        return StringUtils.strQ2B(tmp_str)

    @staticmethod
    def get_string_md5(input_str):
        return hashlib.md5(input_str).hexdigest()

class FTPUtils:

    @staticmethod
    def connect_ftp():
        ftp = FTP(settings.FTP_CONNECTION['url'])
        ftp.login(settings.FTP_CONNECTION['user'], settings.FTP_CONNECTION['password'])
        return ftp

    @staticmethod
    def get_file_as_string(ftp_conn, file_name):
        r = StringIO()
        ftp_conn.cwd(settings.FTP_CONNECTION['default_path'])
        ftp_conn.retrbinary('RETR ' + file_name, r.write)
        return r.getvalue().decode(settings.FTP_CONNECTION['encoding'])

    @staticmethod
    def close_ftp(ftp_conn):
        if ftp_conn != None:
            ftp_conn.close()

    @staticmethod
    def convert_to_edition_suffix(edition_num):
        return '0' + str(int(edition_num) + 1)

class WordSegUtils:
    # 分词http调用
    @staticmethod
    def word_segment_phrase(unicode_text):
        return WordSegUtils.__word_segment(unicode_text, settings.WORD_SEG_TYPE_PHRASE)

    @staticmethod
    def __word_segment(unicode_text, seg_type):
        # 全角转半角，用utf-8编码 
        text = StringUtils.strQ2B(unicode_text).encode(settings.DEFAULT_ENCODING) 
        seg_params = urllib.urlencode({'inputText': text, 'segmentType': seg_type})
        seg_headers = {"Content-type": "application/x-www-form-urlencoded",
            "Accept": "text/plain"}
        seg_conn = httplib.HTTPConnection(settings.WORD_SEG_SERVICE_URL)
        seg_conn.request("POST", settings.WORD_SEG_SERVICE_NAME, seg_params, seg_headers)
        response = seg_conn.getresponse()
        seg_results = response.read()
        seg_tokens = json.loads(seg_results)
        return seg_tokens
 
class RedisUtils:
    # Redis服务工具

    @staticmethod
    def connect_redis(host=settings.REDIS_HOST,
                      port=settings.REDIS_PORT, 
                      db=settings.REDIS_DB_NO):
        redis_conn = redis.StrictRedis(host, port, db)
        return redis_conn
 
    @staticmethod
    def get_daily_news_by_category(redis_conn, date_str, category):
        return RedisUtils.__get_set_members(redis_conn,
                                            category + \
                                            settings.REDIS_DATA_KEY_DELIMITER + \
                                            date_str)
   
    @staticmethod
    def get_daily_headlines(redis_conn, date_str):
        return RedisUtils.__get_set_members(redis_conn,
                                            NewsCategory.HEADLINE + \
                                            settings.REDIS_DATA_KEY_DELIMITER + \
                                            date_str)
    @staticmethod
    def get_daily_frontpages(redis_conn, date_str):
        return RedisUtils.__get_set_members(redis_conn,
                                            NewsCategory.FRONTPAGE + \
                                            settings.REDIS_DATA_KEY_DELIMITER + \
                                            date_str)

    @staticmethod
    def get_daily_morning_reports(redis_conn, date_str):
        return RedisUtils.__get_set_members(redis_conn,
                                            NewsCategory.MORNING_REPORT + \
                                            settings.REDIS_DATA_KEY_DELIMITER + \
                                            date_str)

    @staticmethod
    def get_daily_stock_news(redis_conn, date_str):
        return RedisUtils.__get_set_members(redis_conn,
                                            NewsCategory.STOCK_NEWS + \
                                            settings.REDIS_DATA_KEY_DELIMITER + \
                                            date_str)

    @staticmethod
    def get_daily_annoucements(redis_conn, date_str):
        return RedisUtils.__get_set_members(redis_conn,
                                            NewsCategory.ANNOUCEMENT + \
                                            settings.REDIS_DATA_KEY_DELIMITER + \
                                            date_str)

    @staticmethod
    def get_daily_industry_news(redis_conn, date_str):
        return RedisUtils.__get_set_members(redis_conn,
                                            NewsCategory.INDUSTRY_NEWS + \
                                            settings.REDIS_DATA_KEY_DELIMITER + \
                                            date_str)

    @staticmethod
    def get_daily_industry_research(redis_conn, date_str):
        return RedisUtils.__get_set_members(redis_conn,
                                            NewsCategory.INDUSTRY_RESEARCH + \
                                            settings.REDIS_DATA_KEY_DELIMITER + \
                                            date_str)


    @staticmethod
    def __get_set_members(redis_conn, set_name):
        return redis_conn.smembers(set_name)

    @staticmethod
    def get_doc_title(redis_conn, doc_url):
        return RedisUtils.__get_doc_attrib(redis_conn, 
                                           doc_url, 
                                           settings.REDIS_DATA_ATTRIBUTE['title'])

    @staticmethod
    def get_doc_content(redis_conn, doc_url):
        return RedisUtils.__get_doc_attrib(redis_conn, 
                                           doc_url, 
                                           settings.REDIS_DATA_ATTRIBUTE['content'])

    @staticmethod
    def get_doc_publisher(redis_conn, doc_url):
        return RedisUtils.__get_doc_attrib(redis_conn, 
                                           doc_url, 
                                           settings.REDIS_DATA_ATTRIBUTE['publisher'])

    @staticmethod
    def get_doc_pubtime(redis_conn, doc_url):
        return RedisUtils.__get_doc_attrib(redis_conn, 
                                           doc_url, 
                                           settings.REDIS_DATA_ATTRIBUTE['pubtime'])

    @staticmethod
    def get_doc_stock_code(redis_conn, doc_url):
        return RedisUtils.__get_doc_attrib(redis_conn, 
                                           doc_url, 
                                           settings.REDIS_DATA_ATTRIBUTE['stock_code'])

    @staticmethod
    def __get_doc_attrib(redis_conn, doc_url, attrib):
        val = redis_conn.hget(doc_url, attrib)
        if val is not None:
            return val.decode(settings.DEFAULT_ENCODING)
        else:
            return None

class WebUtils: 
    @staticmethod
    def open_url(url, url_charset, default_charset): 
        html_contents = ""
        try:
            req = urllib2.Request(url)
            resq = urllib2.urlopen(req,timeout = settings.URL_OPEN_TIMEOUT)
            html_contents = resq.read()  
            if url_charset != default_charset:
                html_contents = html_contents.decode(url_charset, 'ignore')
                return html_contents  
        except Exception as e:
            logger.exception(e)
            raise e

class SimhashDeduperUtils:

    @staticmethod
    def hamming_distance(hash1, hash2):
        b = len(bin(hash1)) - 2
        xor_bits = x = (hash1 ^ hash2) & ((1 << b) - 1)
        tot = 0
        while x:
            tot += 1
            x &= x-1

        return tot#, xor_bits, b

    @staticmethod
    def calc_set_similarity(text1, text2):
        #according to the hanzi 
        set1 = set(text1)
        set2 = set(text2)

        return float(len(set1.intersection(set2))) / len(set1.union(set2))

class TextCounter:

    '''
    统计最高频摘要词个数
    '''
    @staticmethod
    def get_top_keywords(keyword_str_list, num_to_return):
        keyword_dict = {}
        if len(keyword_str_list) > 0:
            for keyword_str in keyword_str_list:
                keyword_list = keyword_str.split(settings.NEWS_KEYWORDS_DELIMITER)
                for keyword in keyword_list:
                    if keyword_dict.has_key(keyword):
                        keyword_dict[keyword] += 1
                    else:
                        keyword_dict[keyword] = 1

            top_keywords_sorted = sorted(keyword_dict.iteritems(), 
                                         key=operator.itemgetter(1), 
                                         reverse=True)[0:num_to_return]
            return [key for key, value in top_keywords_sorted]
        else:
            return None
